# coding=utf8
__author__ = 'lijian'
import struct
import bcdUtil
import datetime


def encodeShort(number):
    bytes = []
    bytes.append(number & 0xff)
    bytes.append(number >> 8)
    return bytes


def decodeShort(data):
    value = data[0]
    value = data[1] << 8 | value
    return value


def encodeShortBigEndian(number):
    bytes = []
    bytes.append(number >> 8)
    bytes.append(number & 0xff)
    return bytes


def decodeShortBigEndian(data):
    value = data[0]
    value = value << 8 | data[1]
    return value


def encodeInt(number):
    bytes = []
    bytes.append(number & 0xff)
    bytes.append((number >> 8) & 0xff)
    bytes.append((number >> 16) & 0xff)
    bytes.append(number >> 24)
    return bytes


def decodeInt(data):
    value = data[0]
    value = value | (data[1] << 8)
    value = value | (data[2] << 16)
    value = value | (data[3] << 24)
    return value


def encodeIntBigEndian(number):
    bytes = []
    bytes.append(number >> 24)
    bytes.append((number >> 16) & 0xff)
    bytes.append((number >> 8) & 0xff)
    bytes.append(number & 0xff)
    return bytes


def decodeIntBigEndian(data):
    value = data[0] << 24
    value = value | (data[1] << 16)
    value = value | (data[2] << 8)
    value = value | (data[3])
    return value


def encodeLong(number):
    # bytes = []
    # bytes.append(number >> 56)
    # bytes.append(number >> 48)
    # bytes.append(number >> 40)
    # bytes.append(number >> 32)
    # bytes.append(number >> 24)
    # bytes.append((number >> 16) & 0xff)
    # bytes.append((number >> 8) & 0xff)
    # bytes.append(number & 0xff)
    # return bytes

    number = [number]
    str = struct.pack('Q', *number)
    raw = struct.unpack('B' * len(str), str)
    return raw

def decodeLong(data):
    str = struct.pack('B' * len(data), *data)
    values = struct.unpack('Q', str)
    return values[0]


def encodeFloat(float):
    number = [float]
    str = struct.pack('f', *number)
    raw = struct.unpack('B' * len(str), str)
    return raw


def decodeFloat(data):
    str = struct.pack('B' * len(data), *data)
    values = struct.unpack('f', str)
    return round(values[0], 3)


_lgDict = {
    4: 0,
    3: 1,
    2: 2,
    1: 3,
    0: 4,
    -1: 5,
    -2: 6,
    -3: 7
}

_lgByteDict = {
    0: 10000,
    1: 1000,
    2: 100,
    3: 10,
    4: 1,
    5: 0.1,
    6: 0.01,
    7: 0.001
}


def encodeA2(value):
    if value >= 999 * 10000 or value <= 0.0001:
        return [0, 0]

    sign = 0
    if value > 0:
        sign = 0
    else:
        sign = 1

    lg = -3
    significantDigit = 0

    v = int(value * 1000)
    significantDigit = v
    while True:
        if v < 999:
            significantDigit = v
            break
        lg += 1
        v = v / 10

    bcd = bcdUtil.numberToBcd(significantDigit, size=2)

    b = sign
    b = b | (_lgDict[lg] << 1)
    bcd[1] = bcd[1] | (b << 4)

    # print formatBytes(bcd)
    return bcd


def decodeA2(bytes):
    bcd = [bytes[0], bytes[1]]
    bcd[1] = bcd[1] & 0x0f

    value = bcdUtil.bcdToNumber(bcd)

    lgByte = bytes[1] >> 5
    p = _lgByteDict[lgByte]
    value = value * p

    return value


def encodeA5(value):
    number = int(value * 10)
    bcd = bcdUtil.numberToBcd(number, 2)
    if value < 0:
        bcd[1] = bcd[1] | 0x80
    return bcd


def decodeA5(bytes):
    number = bcdUtil.bcdToNumber(bytes)
    value = number / 10.0
    return value


def encodeA7(value):
    floatValue = round(value, 1)
    intValue = int(floatValue * 10)
    bcd = bcdUtil.numberToBcd(intValue, size=2)
    return bcd

def decodeA7(bytes):
    number=bcdUtil.bcdToNumber(bytes)
    value = number / 10.0
    return value

def encodeA15(t):
    value = []

    value.append(t.minute)
    value.append(t.hour)
    value.append(t.day)
    value.append(t.month)
    value.append(t.year - 2000)

    return bcdUtil.hexTobcd(value)


def encodeA25(value):
    floatValue = round(value, 3)
    intValue = int(floatValue * 1000)
    bcd = bcdUtil.numberToBcd(intValue, size=3)
    return bcd

def decodeA25(bytes):
    value=bcdUtil.bcdToNumber(bytes)
    value=value/1000.0
    return value


def byteToStr(bytes):
    str = ""
    for b in bytes:
        str += hex(b).replace("0x", "") + " "
    return str


def getByte(data):
    if not data or len(data) == 0:
        return None
    else:
        return data[0]


def getBytes(data, size):
    if not data or len(data) == 0:
        return 0, None

    if len(data) < size:
        remainSize = len(data)
        return remainSize, data
    else:
        return size, data[0:size]


def formatBytes(raw):
    if not raw:
        return ""

    str = ""
    for char in raw:
        str = str + "%02X " % char
    return str


def compareList(list1, list2):
    if len(list1) != len(list2):
        return False

    str1 = struct.pack('B' * len(list1), *list1)
    str2 = struct.pack('B' * len(list2), *list2)

    return str1 == str2


def strToBytes(str, size):
    raw = list(struct.unpack('B' * len(str), str))
    if len(raw) < size:
        p = [0] * (size - len(raw))
        raw.extend(p)
    return raw


def strToBool(s):
    l = s.lower()
    if l == "true":
        return True
    else:
        return False


def encodeDayMonthYear(str):
    date = datetime.datetime.strptime(str, "%Y-%m-%d")
    raw = [date.day, date.month, date.year - 2000]
    bcd = bcdUtil.hexTobcd(raw)
    return bcd